查看原文
其他

浅入浅出数据分析之Hello NumPy系列(三)

小一 小一的学习笔记 2023-01-01

2020,努力做一个无可替代的人!


作者 | 小一

全文共3308字,阅读全文需11分钟



写在前面的话

NumPy 第三小节,同学们自行复习第一二小节:

疫情严峻,有空多学习,没事多看看文章,期待阳春三月!

高阶部分篇篇都是干货,建议大家不要错过任何一节内容,最好公众号加星标,方便看到每次的文章推送。



正文

前面在创建 NumPy 数组的时候,通过创建方法可以发现有些类似于线性代数,比如创建的正态分布数组、对角数组等,也确实是这样,矩阵的一些特性 NumPy 同样具有。

先来看一下四则运算:

创建维度相同的两个数组,数组1的值分别为0-5,数组2是一个全1数组

# 创建 2行3列的二维数组
data_arr1 = np.arange(6).reshape(23)
# 输出
[[0 1 2]
 [3 4 5]]

# 创建 2行3列的全1数组
data_ones = np.ones((23), dtype=np.int)
# 输出
[[1 1 1]
 [1 1 1]]

ok,数组创建完毕,试着进行计算

# 数组加法运算
data_arr1 + data_ones
# 输出
[[1 2 3]
 [4 5 6]]

# 数组除法运算
data_ones / (data_arr1 + data_ones)
# 输出
[[1.         0.5        0.33333333]
 [0.25       0.2        0.16666667]]

和我们实际进行数组计算的一致,数组之间的任何算术运算都会应用到元素级。

但是,这个前提是两个数组的维度一致,如果,不一致?或者是个数呢?

看例子:

# 数组与标量的算术运算
data_arr1 * 5
# 输出
[[ 0  5 10]
 [15 20 25]]

同样,数组与标量的算术运算也会将标量的值传播到各个元素。

不同大小数组之间的运算叫做广播。暂且不解释,我们下节专门说它。

再来看下矩阵运算

在线性代数中,有矩阵转置,在 NumPy 中,也就有了数组转置。

转置(transpose)是一种数组维度重塑的一种特殊形式,它返回的是源数据的视图

数组不仅有 transpose 方法,还有一个特殊的 T 属性。

data_arr1
# 输出
[[0 1 2]
 [3 4 5]]

# 转置操作的两种实现方法
data_arr1.T
data_arr1.transpose()
# 输出
[[0 3]
 [1 4]
 [2 5]]

在进行矩阵运算时,比如我们需要计算矩阵内积:X[T]X,可以使用 np.dot 计算

根据公式:矩阵内积 = X 的转置乘以 X

# 创建数组
data_arr2 = np.random.randn(1,3)
# 输出
[[-0.14205835 -1.43319166  0.8389062 ]]

# 计算矩阵内积
np.dot(data_arr2.T, data_arr2)
# 输出
[[ 0.02018058  0.20359685 -0.11917363]
 [ 0.20359685  2.05403832 -1.20231337]
 [-0.11917363 -1.20231337  0.70376361]]

还有高维数组的转置这些,实际上并不常用,而且也不是很好理解,就不再提了,最常用的就是二维数组的转置,会这个就可。

列举部分线性代数在 NumPy 的实现

函数说明
dot矩阵乘法
trace计算对角线元素的和
det计算矩阵行列式
inv计算方阵的逆
solve解线性方程组 Ax = b,其中 A 为一个方阵
lstsq计算 Ax = b 的最小二乘解
…………
通用函数

通用函数(即 ufunc)是一种对 ndarray 中的数据执行元素级运算的函数。

你可以将其看做简单函数的矢量化包装器:接受一个或多个标量值,并产生一个或多个标量值。

先来看看一元通用函数(unary ufunc)

# 创建数组
data_unary = np.arange(10)
# 输出
[0 1 2 3 4 5 6 7 8 9]

# 求数组每个元素的平方根
np.sqrt(data_unary)
# 输出
[0.         1.         1.41421356 1.73205081 2.         2.23606798
 2.44948974 2.64575131 2.82842712 3.        ]

# 求数组的最大最小值
np.min(data_unary)
np.max(data_unary)
# 输出
0
9

就和 Python 的常规语法一样,NumPy 通用函数也是直接调用即可。

另外还有一些接受2个数组,返回一个结果数组的通用函数(二元函数)

列举一些常用的一元和二元函数


函数说明
一元abs计算整数、浮点数或负数的绝对值。
一元sqrt计算个元素的平方根
一元square计算各元素的平凡
一元exp计算各元素的指数
一元log、log10、log2分别为底数为e的log、底数为10的log、底数为2的log
一元sign计算各元素的正负号
一元ceil计算各元素的ceiling值(大于等于该值的最小整数)
一元floor计算各元素的floor值(小于等于该值的最大整数)
一元cos、cosh、sin、sinh、tan、tanh普通和双曲线三角函数
一元isnan返回一个数组表示”哪些是NaN“的布尔型数组
………………
二元add将数组中对应的元素相加
二元sutract从第一个数组中减去第二个数组中的元素
二元multiply数组元素相乘
二元divide数组元素相除
二元power计算 A 的 B 次方
………………

是不是以为到这就结束了?

没错,快结束了,但是我总觉得下面的内容才是今天的重点内容,信不信由你。

条件逻辑表述

我们都知道 Python 中的三元表达式:x if condition else y

那如果我们有两个值数组分别表示 x 和 y,有一个布尔数组表示 condition,如何进行条件逻辑表述呢?

# 创建数组
data_xarr = np.array([12345])
data_yarr = np.array([-1-2-3-4-5])
data_tag = np.array([TrueFalseFalseFalseTrue])

根据布尔数组 data_tag 选取 data_xarr 和 data_yarr 的值:当 data_tag 为 True,选择 data_xarr 的值,否则从 data_yarr 中选取。

先来看一下列表推导式:

# 实现三元表达式功能
result = [(x if tag else y) 
            for x, y, tag in zip(data_xarr, data_yarr, data_tag)
         ]

# 输出
[1-2-3-45]

是不是很麻烦?

NumPy 中一个函数就可以实现上面的功能!!!

# 使用 where 函数实现三元表达式功能
result = np.where(data_tag, data_xarr, data_yarr)

# 输出
1 -2 -3 -4  5]

是不是很方便?就问你香不香?

解释一下 where 函数的用法:第一个参数是条件 condition,第二和第三个参数相当于三元表达式中的 x 和 y

其中 x 和 y 不必是数组,也可以是标量值, where 函数返回一个新的数组。

例如,通过 where 函数进行数据清洗,大于0的数全部置为1,小于0的数全部置为-1

# 创建 3*3 的数组
data_warr = np.random.randn(33)
# 输出
[[-0.57519374  0.91571952  0.2104197 ]
 [ 0.32693672  0.95512399 -0.09581747]
 [-1.40553911 -0.96782964  0.73291699]]

# 大于0的数全部置为1,小于0的数全部置为-1
result = np.where(data_warr>01-1)
# 输出
[[-1  1  1]
 [ 1  1 -1]
 [-1 -1  1]]

如果要保留小于0的数组值,只替换大于0的值呢?

# 保留小于0的数组值,只替换大于0的值
np.where(data_warr>01, data_warr)
# 输出
[[-0.57519374  1.          1.        ]
 [ 1.          1.         -0.09581747]
 [-1.40553911 -0.96782964  1.        ]]
比 where 更重要的内容

布尔判断+统计,你没听错,数据分析常用

举例:随机数中所有大于0的数的和、平均值、标准差方差等

# 创建10个范围在-10~10的随机整数
data_rn = np.random.randint(-101010)
# 输出
[-9 -2 -1 -7  9  9 -4  6  3 -1]

# 大于0的所有数的和、平均值、标准差方差
(data_rn>0).sum()
(data_rn>0).mean()
(data_rn>0).std()
(data_rn>0).var()
# 输出
4
0.4
0.48989794855663565
0.24000000000000005

any、how 检测

any 用于测试数组中是否存在一个或多个 True

all 用于检查数组中所有值是否都是 True

sort 排序

和 Python 内置的列表类型一样,NumPy 数组也可以通过 sort 方法进行排序

data_sort = np.array([[10-254], [-1-3342]])
# 输出
[[ 1  0 -2  5  4]
 [-1 -3  3  4  2]]

# 默认排序(行)
data_sort.sort()
# 输出
[[-2  0  1  4  5]
 [-3 -1  2  3  4]]

# 在0轴上排序(列)
data_sort.sort(axis=0)
# 输出
[[-3 -1  1  3  4]
 [-2  0  2  4  5]]

unique 唯一化

针对一维数组最常用的基本集合运算:unique 用于找出数组中的唯一值并返回已排序的结果

# `unique 找出数组中的唯一值并返回已排序的结果`
data_ints = np.array([23112467-1])
np.unique(data_ints)

# 输出
[-1  1  2  3  4  6  7]

呼呼,没骗你吧,这才是最实用的内容。

总结一下:

说实话,今天的内容挺多的。

总结一下:
  • NumPy 数组的四则运算

  • NumPy 数组的矩阵运算

  • 条件逻辑表述 where

  • 布尔判断、统计、排序、唯一化

前两小节属于运算中比较基础的内容,知道是什么、怎么用就可以了。

重点是后面两小节,在实际项目中用处很大,建议大家看着例子多读几篇。

可以的话,在自己电脑上运行一遍试试

写在后面的话

透个底,NumPy 系列在我的计划中还有最后一篇,今天是第三篇。

不知道大家学的怎么样,有的内容了解就行,也没必要死磕下去。

当然,我标重点还是建议都掌握啦,下期见!

碎碎念一下

最全的干货已经开始了,大家不要掉队啊。

建议大家在公众号加星标,不要错过高阶内容!



Python 系列入门:准备工作  运算符  数据类型①  数据类型②  流程控制  函数  文件  模块  异常进阶:面向对象  正则表达式  多线程与多进程  JSON操作  时间序列  数据库操作  邮件发送高阶:事半功倍的高阶函数  NumPy系列①  NumPy系列②技巧:学习技巧①  学习技巧②  学习技巧③爬虫系列

基础:准备工作  爬虫实现方式  Requests详解  BeautifulSoup详解

进阶:获取动态数据①  获取动态数据②

实战:爬取豆瓣电影  豆瓣电影分析  爬取链家租房  每日疫情数据自动化

其他系列

学排版:Markdown排版教程

领资料:100G+数据分析资料免费领

非技术系列讲故事:小一的故事  和二三四们的故事听故事:投稿故事①投故事:看故事之前先看我



好巧啊,你也读到这了!    

点个在看让我看到你

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存